<template>
  <div
    class="song-player"
    :class="{ 'default-size': isDisplay }"
  >
    <div class="btn">
      <el-button
        type="primary"
        :icon="isDisplay ? ArrowDownBold : ArrowUpBold"
        circle
        @click="isDisplay = !isDisplay"
      />
    </div>
    <div class="content">
      <p>
        <img
          id="t-img"
          :src="imgUrl"
          alt=""
        />
      </p>
      <p>{{ songName }}</p>
      <p>
        <el-button
          class="b-btn"
          type=""
        >
          <el-icon
            :size="50"
            @click="changeMusic(-1)"
          >
            <Back />
          </el-icon>
        </el-button>
        <el-button
          class="b-btn"
          type=""
        >
          <el-icon :size="50">
            <VideoPause
              v-if="isPlay"
              @click="musicCtrl(false)"
            />
            <VideoPlay
              v-else
              @click="musicCtrl(true)"
            />
          </el-icon>
        </el-button>
        <el-button
          class="b-btn"
          type=""
          @click="changeMusic(1)"
        >
          <el-icon :size="50">
            <Right />
          </el-icon>
        </el-button>
      </p>
      <div class="slider">
        <el-icon
          :size="15"
          class="ei"
        >
          <Headset />
        </el-icon>
        <el-slider
          v-model="voice"
          :max="1"
          :step="0.01"
        />
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, onUpdated, ref, watch } from 'vue'
import { ArrowDownBold, ArrowUpBold, Back, Headset, Right, VideoPause, VideoPlay } from '@element-plus/icons-vue'
import { useUserStore } from '@/stores/userStore.ts'
import { Howl } from 'howler'
import type { UnifyResponse } from '@/types/result'
import type { PlayListItem } from '@/types/song'
import { postPlayListAPI } from '@/services/songService.ts'

const isDisplay = ref<boolean>(false)
const isPlay = ref<boolean>(false)
const userStore = useUserStore()
const voice = ref<number>(0)

const sound = ref<Howl>()

const musicUrl = computed(() => {
  if (userStore.songsList[userStore.songsListPosition]) {
    return 'http://localhost:8888' + userStore.songsList[userStore.songsListPosition].songVO.fileUrl
  } else {
    return ''
  }
})

const imgUrl = computed(() => {
  if (userStore.songsList[userStore.songsListPosition]) {
    return 'http://localhost:8888' + userStore.songsList[userStore.songsListPosition].songVO.tinyImg
  } else {
    return ''
  }
})

const songName = computed(() => {
  if (userStore.songsList[userStore.songsListPosition]) {
    return userStore.songsList[userStore.songsListPosition].songVO.name
  } else {
    return '无音乐'
  }
})

const initPlayer = (url: string, volume: number) => {
  sound.value?.unload()
  sound.value = new Howl({
    src: [url],
    pool: 1,
    volume,
    onend: () => {
      sound.value?.unload()
      changeMusic(1)
    },
  })
}

const beforeChange = () => {
  sound.value?.unload()
  initPlayer(musicUrl.value, voice.value)
  sound.value?.play()
  isPlay.value = true
}

watch(voice, newVoice => {
  if (sound.value) {
    sound.value.volume(newVoice)
  }
})

watch(
  userStore.songsList,
  () => {
    if (userStore.songsList.length > 0) {
      beforeChange()
    }
  },
  {
    deep: true,
  }
)

watch(
  () => userStore.songsListPosition,
  () => {
    beforeChange()
  }
)

watch(
  () => userStore.isOpen,
  () => {
    beforeChange()
  }
)

const changeMusic = (step: number) => {
  userStore.songsListPosition += step
  if (userStore.songsListPosition >= userStore.songsList.length) {
    userStore.songsListPosition = 0
    initPlayer(musicUrl.value, voice.value)
  } else if (userStore.songsListPosition < 0) {
    userStore.songsListPosition = userStore.songsList.length - 1
    initPlayer(musicUrl.value, voice.value)
  } else {
    initPlayer(musicUrl.value, voice.value)
  }
  sound.value!.play()
}

const musicCtrl = (isOpen: boolean) => {
  if (sound.value == null) {
    return
  }
  if (isOpen) {
    sound.value?.play()
    isPlay.value = true
  } else {
    sound.value?.pause()
    isPlay.value = false
  }
}

onUpdated(async () => {
  if (userStore.token != null) {
    try {
      const res: UnifyResponse<PlayListItem[]> = await postPlayListAPI()
      if (res.data !== null) {
        userStore.songsList = res.data
      }
    } catch (e) {
      console.error(e)
    }
  }
})

onMounted(() => {
  if (userStore.songsList.length > 0) {
    initPlayer(musicUrl.value, voice.value)
  }
})
</script>

<style scoped>
.song-player {
  position: relative;
  width: 25em;
  height: 1em;
  background: #15789c;
  border-top-left-radius: 2em;
  border-top-right-radius: 2em;
  transition: 0.5s;
}

.default-size {
  height: 28em;
  background: #18aa88;
}

.btn {
  position: absolute;
  top: -2em;
  left: 50%;
  transform: translateX(-50%);
}

.content {
  display: flex;
  flex-direction: column;
  height: 100%;
}

p {
  text-align: center;
  font-weight: bold;
  font-size: 1em;
  margin-top: 0.5em;
}

#t-img {
  width: 12em;
  height: 12em;
  border: #000000 solid 3px;
  margin-top: 4em;
}

.b-btn {
  width: 6em;
  height: 5em;
  background-color: transparent;
}

p:last-child {
  margin-top: 1em;
}

.slider {
  width: 15em;
  margin: 1em auto;
  display: flex;
  align-items: center;
}

.slider .ei {
  margin-right: 2em;
}
</style>
